<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>双摇杆控制器与视频流</title>
    <style>
        body {
            display: flex;
            flex-direction: column;
            align-items: center;
            font-family: Arial, sans-serif;
            background-color: #f0f0f0;
            margin: 0;
            height: 100vh;
            position: relative;
        }
        .joystick-container {
            position: absolute;
            bottom: 100px;
            left: 100px;
            right: 100px;
            display: flex;
            justify-content: space-between;
        }
        .joystick {
            width: 150px;
            height: 150px;
            background-color: #ddd;
            border-radius: 50%;
            position: relative;
            touch-action: none;
        }
        .handle {
            width: 50px;
            height: 50px;
            background-color: #333;
            border-radius: 50%;
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }
        .output {
            margin: 10px;
            font-size: 18px;
            text-align: center;
        }
        .left-joystick {
            margin-left: 0;
        }
        .right-joystick {
            margin-right: 0;
        }
        .video-container {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 640px;
            height: 480px;
            background-color: #000;
        }
        #webcam {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        .button-container {
            display: flex;
            justify-content: center;
            gap: 20px;
            margin-top: 20px;
            flex-wrap: wrap;
        }

        .control-button {
            padding: 15px 30px;
            font-size: 16px;
            background-color: #4CAF50;  /* 默认绿色 */
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            transition: all 0.3s ease;
            min-width: 120px;
            position: relative;
            overflow: hidden;
        }

        .control-button:hover {
            background-color: #45a049;
            transform: scale(1.05);
        }

        .control-button:active {
            transform: scale(0.95);
        }

        .control-button.active {
            background-color: #ff4444;  /* 按下时红色 */
        }

        .button-status {
            position: absolute;
            top: 5px;
            right: 5px;
            font-size: 12px;
            opacity: 0.8;
        }

        @media (max-width: 768px) {
            .button-container {
                gap: 10px;
            }
            
            .control-button {
                padding: 12px 24px;
                font-size: 14px;
                min-width: 100px;
            }
        }
    </style>
</head>
<body>
    <h1>双摇杆控制器与视频流</h1>
    <div class="video-container">
        <img id="webcam" src="http://192.168.31.116:8080/api/webcam/stream" alt="Webcam Stream">
    </div>
    <div class="joystick-container">
        <div class="left-joystick">
            <h3>左摇杆</h3>
            <div id="leftJoystick" class="joystick">
                <div class="handle"></div>
            </div>
            <div id="leftOutput" class="output">X: 0, Y: 0</div>
        </div>
        <div class="right-joystick">
            <h3>右摇杆</h3>
            <div id="rightJoystick" class="joystick">
                <div class="handle"></div>
            </div>
            <div id="rightOutput" class="output">X: 0, Y: 0</div>
        </div>
    </div>
    <div class="button-container">
        <button class="control-button" id="button1">
            按钮 1
            <span class="button-status">0</span>
        </button>
        <button class="control-button" id="button2">
            按钮 2
            <span class="button-status">0</span>
        </button>
        <button class="control-button" id="button3">
            按钮 3
            <span class="button-status">0</span>
        </button>
        <button class="control-button" id="button4">
            按钮 4
            <span class="button-status">0</span>
        </button>
    </div>

    <script>
        const BASE_URL = 'http://192.168.31.116:8080';

        class Joystick {
            constructor(joystickId, outputId, type) {
                this.joystick = document.getElementById(joystickId);
                this.handle = this.joystick.querySelector('.handle');
                this.output = document.getElementById(outputId);
                this.type = type;  // 'left' 或 'right'
                this.isDragging = false;
                this.touchId = null;
                this.centerX = this.joystick.offsetWidth / 2;
                this.centerY = this.joystick.offsetHeight / 2;
                this.maxDistance = this.joystick.offsetWidth / 2 - this.handle.offsetWidth / 2;
                this.lastSentX = 0;
                this.lastSentY = 0;
                this.sendInterval = 5; // 降低发送间隔到5ms
                this.lastSendTime = 0;
                this.threshold = 0.01; // 降低阈值，使响应更敏感
                this.ws = null;
                this.initWebSocket();

                this.joystick.addEventListener('mousedown', this.startDrag.bind(this));
                this.joystick.addEventListener('touchstart', this.startDrag.bind(this));
                this.joystick.addEventListener('mousemove', this.moveHandle.bind(this));
                this.joystick.addEventListener('touchmove', this.moveHandle.bind(this));
                this.joystick.addEventListener('mouseup', this.stopDrag.bind(this));
                this.joystick.addEventListener('touchend', this.stopDrag.bind(this));
                this.joystick.addEventListener('touchcancel', this.stopDrag.bind(this));
            }

            initWebSocket() {
                const connectWebSocket = () => {
                    // 使用完整的IP地址和端口
                    const wsUrl = 'ws://192.168.31.116:9090';
                    console.log('正在连接WebSocket:', wsUrl);
                    this.ws = new WebSocket(wsUrl);
                    
                    this.ws.onopen = () => {
                        console.log('WebSocket连接已建立');
                        // 连接成功后发送一个测试消息
                        this.ws.send(JSON.stringify({
                            type: this.type,
                            x: 0,
                            y: 0
                        }));
                    };
                    
                    this.ws.onclose = (event) => {
                        console.log('WebSocket连接已关闭，代码:', event.code, '原因:', event.reason);
                        // 如果连接关闭，等待1秒后重试
                        setTimeout(connectWebSocket, 1000);
                    };
                    
                    this.ws.onerror = (error) => {
                        console.error('WebSocket错误:', error);
                        // 发生错误时关闭连接，触发重连
                        this.ws.close();
                    };

                    // 添加消息接收处理
                    this.ws.onmessage = (event) => {
                        console.log('收到服务器消息:', event.data);
                    };
                };
                
                connectWebSocket();
            }

            sendJoystickData(x, y) {
                const now = Date.now();
                if (now - this.lastSendTime < this.sendInterval) {
                    return;
                }

                // 只有当数据变化超过阈值时才发送
                if (Math.abs(x - this.lastSentX) < this.threshold && Math.abs(y - this.lastSentY) < this.threshold) {
                    return;
                }

                if (this.ws && this.ws.readyState === WebSocket.OPEN) {
                    try {
                        const data = JSON.stringify({
                            type: this.type,
                            x: x,
                            y: y
                        });
                        this.ws.send(data);
                        this.lastSentX = x;
                        this.lastSentY = y;
                        this.lastSendTime = now;
                    } catch (error) {
                        console.error('发送摇杆数据失败:', error);
                        // 如果发送失败，尝试重新连接
                        this.ws.close();
                    }
                } else {
                    console.log('WebSocket未连接，当前状态:', this.ws ? this.ws.readyState : '未初始化');
                }
            }

            startDrag(event) {
                event.preventDefault();
                if (event.type === 'touchstart') {
                    this.touchId = event.changedTouches[0].identifier;
                    this.isDragging = true;
                    this.moveHandle(event);
                } else if (event.type === 'mousedown') {
                    this.isDragging = true;
                    this.moveHandle(event);
                }
            }

            moveHandle(event) {
                if (!this.isDragging) return;

                let clientX, clientY;
                if (event.type === 'touchmove') {
                    let touch = null;
                    for (let t of event.changedTouches) {
                        if (t.identifier === this.touchId) {
                            touch = t;
                            break;
                        }
                    }
                    if (!touch) return;
                    clientX = touch.clientX;
                    clientY = touch.clientY;
                } else if (event.type === 'mousemove') {
                    clientX = event.clientX;
                    clientY = event.clientY;
                } else {
                    return;
                }

                const rect = this.joystick.getBoundingClientRect();
                let x = clientX - rect.left - this.centerX;
                let y = clientY - rect.top - this.centerY;

                const distance = Math.sqrt(x * x + y * y);
                if (distance > this.maxDistance) {
                    const angle = Math.atan2(y, x);
                    x = Math.cos(angle) * this.maxDistance;
                    y = Math.sin(angle) * this.maxDistance;
                }

                this.handle.style.left = `${this.centerX + x}px`;
                this.handle.style.top = `${this.centerY + y}px`;

                const normalizedX = (x / this.maxDistance).toFixed(2);
                const normalizedY = (y / this.maxDistance).toFixed(2);
                this.output.textContent = `X: ${normalizedX}, Y: ${normalizedY}`;

                // 发送摇杆数据到后端
                this.sendJoystickData(parseFloat(normalizedX), parseFloat(normalizedY));
            }

            stopDrag(event) {
                if (event.type === 'touchend' || event.type === 'touchcancel') {
                    let touch = null;
                    for (let t of event.changedTouches) {
                        if (t.identifier === this.touchId) {
                            touch = t;
                            break;
                        }
                    }
                    if (!touch) return;
                }
                this.isDragging = false;
                this.touchId = null;
                this.handle.style.left = `${this.centerX}px`;
                this.handle.style.top = `${this.centerY}px`;
                this.output.textContent = `X: 0, Y: 0`;
                
                // 发送归零数据
                this.sendJoystickData(0, 0);
            }
        }

        // 初始化摇杆
        const leftJoystick = new Joystick('leftJoystick', 'leftOutput', 'left');
        const rightJoystick = new Joystick('rightJoystick', 'rightOutput', 'right');

        // 按钮处理
        document.querySelectorAll('.control-button').forEach(button => {
            let isPressed = false;
            const statusSpan = button.querySelector('.button-status');
            
            button.addEventListener('click', async function() {
                isPressed = !isPressed;  // 切换状态
                if (isPressed) {
                    this.classList.add('active');
                    statusSpan.textContent = '1';
                } else {
                    this.classList.remove('active');
                    statusSpan.textContent = '0';
                }
                
                const buttonId = this.id.replace('button', '');
                try {
                    await fetch(`${BASE_URL}/api/button?id=${buttonId}&state=${isPressed ? '1' : '0'}`, {
                        method: 'POST'
                    });
                } catch (error) {
                    console.error(`按钮${buttonId}请求失败:`, error);
                }
            });
        });
    </script>
</body>
</html>